package com.google.code.netbuilder.services.equipment;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import com.google.code.netbuilder.dal.entities.Equipment;
import com.google.code.netbuilder.dal.entities.Port;
import com.google.code.netbuilder.dal.entities.EquipmentTemplate;
import com.google.code.netbuilder.dal.providers.IEquipmentTemplateProvider;
import com.google.code.netbuilder.dal.providers.IProviderManager;

/**
 * Loading template from DB and creating equipment with appropriate fields
 * uses Prepared Equipment for unmarshalling
 * @author Sergey Kozlov
 *
 */
@Stateless
public class EquipmentTemplateLoader implements IEquipmentTemplateLoader{
	
	@EJB
	private IEquipmentTemplateProvider etp;
	
//	@EJB
//	private IProviderManager pm;
		
	public EquipmentTemplateLoader(){
		
	}
	
//	@PostConstruct
//	void init(){
//		
//		System.err.println("pp found?");
//		etp = (IEquipmentTemplateProvider) pm.getProvider("equipmentTemplate", "JPA");
//	}
	
	/**
	 * Looks for EquipmentTemplate with specified name in DB
	 * @param templateName
	 * name of template to look for
	 * @return
	 * EquipmentTemplate object
	 */
	private EquipmentTemplate findTemplate(String templateName){
		if(templateName == null){
			throw new IllegalArgumentException("Equipment name can't be null");
		}
		EquipmentTemplate et = null;
		try{
			et = etp.findByName(templateName);
		}catch(NoResultException nre){
			nre.printStackTrace();
			throw new IllegalArgumentException("No equipment template with name " + templateName + "found");
		}
		return et;		
	}
	
	/**
	 * Unmarshall xml of EquipmentTemplate and fills Equipment fields with corresponding data
	 * @param et
	 * EquipmentTemplate object
	 * @return
	 * Equipment object with fields loaded according EquipmentTemplate
	 */
	private Equipment loadEquipment(EquipmentTemplate et){

		System.out.println("Loading equipment from template: " + et.getName() + " with xml: " +  et.getXml());
		StringReader reader = new StringReader(et.getXml());
		Equipment e = null;
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance(PreparedEquipment.class);
			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
			PreparedEquipment pE = (PreparedEquipment)unmarshaller.unmarshal(reader);
			
			e = new Equipment();
			e.setName(pE.getPrototypeName());
			e.setType(pE.getType());
						
			Integer numberOfPorts = pE.getNumberOfPorts();
			List<Port> ports = new ArrayList<Port>();
			Port pA;
			Port pB;
			
			for (int i = 0; i < numberOfPorts.intValue(); i++){
				pA = new Port();
				int a = i+1;
				pA.setName("A-" + a);
				pB = new Port();
				pB.setName("B-" + a);
				pA.setInnerConnectedPort(pB);
				pB.setInnerConnectedPort(pA);
				ports.add(pA);
				ports.add(pB);
			}
			
			e.setPorts(ports);
			
			
		}catch (JAXBException ex) {
			System.err.println("Unable to unmarshall xml: " + et.getXml());
			ex.printStackTrace();
		}		
		return e;
	}
	
	@Override
	public Equipment loadEquipmentFromTemplateName(String templateName){
		EquipmentTemplate et = findTemplate(templateName);
		Equipment e = loadEquipment(et);
		return e;
	}

	
	
}
